package org.nhindirect.stagent;

public class StringSegment 
{
	
	
    String m_source;
    int m_startIndex;
    int m_endIndex;

	public static StringSegment createNull()
	{
		return new StringSegment(null);
	}

    
    public StringSegment(String source)
    {
        this.m_source = source;
        this.m_startIndex = 0;
        if (source == null)
        {
            this.m_endIndex = -1;
        }
        else
        {
            this.m_endIndex = source.length() - 1;
        }
    }
    
    public StringSegment(String source, int startIndex, int endIndex)
    {
        if (source == null)
        {
            throw new IllegalArgumentException();
        }
        if (startIndex < 0 || startIndex > source.length())
        {
            throw new IllegalArgumentException("startIndex");
        }
        if (endIndex < -1 || endIndex >= source.length())
        {
            throw new IllegalArgumentException("endIndex");
        }

        this.m_source = source;
        this.m_startIndex = startIndex;
        this.m_endIndex = endIndex;
    }
    
    public char charAt(int index)
    {
       return this.m_source.charAt(this.m_startIndex + index);
    }
            
    public String getSource()
    {
        return this.m_source;
    }
    
    public int getLength()
    {
       return (this.m_endIndex - this.m_startIndex + 1);
    }
    
    public boolean isEmpty()
    {
       return (this.getLength() == 0);
    }
    
    public boolean isNull()
    {
       return (this.m_source == null);
    }
    
    public int getStartIndex()
    {

        return this.m_startIndex;

    }

    void setStartIndex(int value)
    {
        if (value > this.m_endIndex)
        {
            throw new IllegalArgumentException();
        }
        
        this.m_startIndex = value;
    }
    
    public int getEndIndex()
    {
        return this.m_endIndex;
    }
    
    @Override
    public String toString()
    {
        int length = this.getLength();
        if (length == 0)
        {
            return "";
        }
        //
        // If the segment covers the entire string, we don't need an allocation
        //
        if (length == this.m_source.length())
        {
            return this.m_source;
        }

        return this.m_source.substring(this.m_startIndex, m_startIndex + length);
    }
    
    public void union(StringSegment segment)
    {
        if (segment.m_source == null)
        {
            throw new IllegalArgumentException("Cannot union with null segment");
        }
        
        if (this.m_source == null)
        {
            this.m_source = segment.m_source;
            this.m_startIndex = segment.m_startIndex;
            this.m_endIndex = segment.m_endIndex;
            return;
        }
        
/*        if (!object.ReferenceEquals(this.m_source, segment.m_source))
        {
            throw new InvalidOperationException("Segments from different strings");
        }
*/
        if (segment.m_startIndex < this.m_startIndex)
        {
            this.m_startIndex = segment.m_startIndex;
        }

        if (segment.m_endIndex > this.m_endIndex)
        {
            this.m_endIndex = segment.m_endIndex;
        }
    }
    
    public String substring(int startAt)
    {
        int length = this.m_endIndex - startAt + 1;
        if (length < 0)
        {
            throw new IndexOutOfBoundsException();
        }
        return this.m_source.substring(startAt, length);
    }

    public String substring(int startAt, int length)
    {
        int endIndex = startAt + length;
        if (endIndex < this.m_startIndex || endIndex > this.m_endIndex)
        {
            throw new IndexOutOfBoundsException();
        }
        return this.m_source.substring(startAt, length);
    }
    
    public boolean equals(String other)
    {
        if (this.getLength() != other.length())
        {
            return false;
        }

        return (String.CASE_INSENSITIVE_ORDER.compare(this.m_source.substring(this.m_startIndex, other.length()), other) == 0);
    }
    
    public boolean equals(StringSegment other)
    {
        if (this.getLength() != other.getLength())
        {
            return false;
        }
        return (String.CASE_INSENSITIVE_ORDER.compare(this.m_source.substring(this.m_startIndex, this.getLength()), 
        		other.getSource().substring(other.getStartIndex(), this.getLength())) == 0);
    }
    
    public boolean startsWith(String other)
    {
        int length = this.getLength();
        if (other.length() > length)
        {
            return false;
        }
        
        return (String.CASE_INSENSITIVE_ORDER.compare(this.m_source.substring(this.m_startIndex, other.length()), other) == 0);
    }
    
    public int indexOf(String other)
    {
        int length = this.getLength();
        if (other.length() > length)
        {
            return -1;
        }
        
        return this.m_source.substring(this.m_startIndex, length).indexOf(other);
    }

}
